/** @file */
#include "ui_mainwindow.h"
#include <QInputDialog>
#include <QMainWindow>
#include <QFileDialog>
#include <QMessageBox>
#include <QString>
#include <QStandardItemModel>
#include <QModelIndex>

#include <iostream>
#include <sstream>
#include <string>

#include "mainwindow.h"
#include "filmbaza.h"
#include "eximport.h"
#include "login.h"
#include "scan.h"

#define TO_STR( x ) ( dynamic_cast< std::ostringstream & >( ( std::ostringstream() << std::dec << x ) ).str() )

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow),
	fb(NULL)
{
    ui->setupUi(this);
	
	this->setWindowTitle("Filmbaza");
	
    this->refresh();

}

MainWindow::~MainWindow()
{
	if ( this->fb )
		filmbaza_destroy(this->fb);
	delete ui;
}

#include <iostream>

void MainWindow::refresh()
{
	const int cols = 3;
	std::string mesg;
	int rows = 0;
	
	/* security */
	if ( !logged() ) {
		print(" You are not logged. Run away and scream.");
		exit(-1);
	} else {
		mesg = "Zalogowowano jako " + get_user() + '\n';
	}
	
	
	/* initialize the table */	
	QStandardItemModel* model = new QStandardItemModel(rows, cols);
	
	/* columns names */
	model->setHeaderData(0, Qt::Horizontal, QObject::tr("Nazwa"));
	model->setHeaderData(1, Qt::Horizontal, QObject::tr("Ocena"));
	model->setHeaderData(2, Qt::Horizontal, QObject::tr("Wypożyczone"));
	
	
	/* for gods sake */
	if ( this->fb ) {
        struct film_s **head = &this->fb->filmy;
		struct film_s *info;
		int row = 0;
		
		/* meh... we need to calculate how many elements we have */
        rows = 0;
        list_for_each(info, head) {
            rows++;
        }
		
		/* fill the model (table) */
		row = 0;
        list_for_each(info, head) {
			QString text = QString(info->name.c_str());
			QStandardItem* item = new QStandardItem(text);
	                model->setItem(row, 0, item);
			
			text = QString::number(info->rate);
			item = new QStandardItem(text);
	                model->setItem(row, 1, item);
			
			text = QString(info->share.shared ? info->share.name.c_str() : (char*)"Nie wypożyczone");
			item = new QStandardItem(text);
	                model->setItem(row, 2, item);
			
			/* increment !! */
			row++;
		}
		
		mesg = mesg + "Nazwa bazy danych: " + fb->name + "\nLiczba filmów w bazie: " + TO_STR(rows);
	} else {
		mesg = mesg + "Nie utworzono bazy danych\n";
	}
	
	
	ui->informuj->clear();
	ui->informuj->append(QString::fromStdString(mesg));
	
	/* set model to the table */
	delete ui->tabka->model();
	ui->tabka->setModel(model);
	ui->tabka->setColumnWidth( 0, 400 );
	ui->tabka->setColumnWidth( 1, 60 );
	ui->tabka->setColumnWidth( 2, 100 );

	/* show or hide menus */
	
	if ( admin() ) {
		ui->menuAdmin->setEnabled(true);
	} else {
		ui->menuAdmin->setEnabled(false);
	}
	
	if ( this->fb ) {
		ui->menuFilmy->setEnabled(true);
		
		ui->actionUsun_filmbaze->setEnabled(true);
		ui->actionEksportuj->setEnabled(true);
		
		ui->actionDodaj_film->setEnabled(true);
		
		ui->actionSkanuj_katalog->setEnabled(true);
		
		ui->buttonUsu_baze->setEnabled(true);
		ui->buttonDodaj_film->setEnabled(true);
		
		/* nie ma co usuwać jesli nie ma filmów */
		if ( rows ) {
			ui->buttonUsu_film->setEnabled(true);
			ui->actionUsu_film->setEnabled(true);
		} else {
			ui->buttonUsu_film->setEnabled(false);
			ui->actionUsu_film->setEnabled(false);
		}
	} else {
		ui->menuFilmy->setEnabled(false);
		
		ui->actionUsun_filmbaze->setEnabled(false);
		ui->actionEksportuj->setEnabled(false);
		
		ui->actionDodaj_film->setEnabled(false);
		
		ui->actionSkanuj_katalog->setEnabled(false);
		
		ui->buttonUsu_baze->setEnabled(false);
		ui->buttonDodaj_film->setEnabled(false);
		
		ui->buttonUsu_film->setEnabled(false);
		ui->actionUsu_film->setEnabled(false);
		
	}
		
	
}

void MainWindow::print(std::string msg)
{
	QMessageBox msgBox;
    msgBox.setText(QString::fromStdString(msg));
        msgBox.exec();
}

void MainWindow::baza_new()
{
    std::string fbname;
	
	bool ok;
    QString text = QInputDialog::getText(this, tr("Nowa baza danych"),
                        tr("Nazwa bazy filmów:").toAscii(), QLineEdit::Normal,
					     QString(), &ok);
	if ( !ok || text.isEmpty() )
	     return;
     
	fbname = text.toStdString();
	
	if ( this->fb )
		filmbaza_destroy(fb);
	this->fb = filmbaza_create(fbname);
	
	this->refresh();
}

void MainWindow::baza_del()
{
	if ( this->fb ) {
		filmbaza_destroy(this->fb);
        this->fb = NULL;
	}
	refresh();
}

void MainWindow::import_base()
{
	QString fn;
	int ret;
	
	fn = QFileDialog::getOpenFileName(this, "Importuj baze filmów", 
		QString(), tr("All files (*)"), NULL, QFileDialog::ReadOnly);
	if (fn.isEmpty())
		return;
	
	if ( !fb ) {
		fb = filmbaza_create("");
		if ( !fb ) 
			print(" Error przy tworzeniu nowej bazy danych.");
	}
	
	ret = filmbaza_import(fb, fn.toStdString());
	if ( ret ) {
		print(" importowanie nie udało się");
		return;
	}
	refresh();
	print("Zaimportowano filmy z pliku " + fn.toStdString());
	
}

void MainWindow::export_base()
{
	QFileDialog fd;
	QString fn;
	int ret;
	
	if ( !fb ) {
		QMessageBox msgBox;
	        msgBox.setText("Baza danych nie została jeszcze utworzona");
	        msgBox.exec();
		return;
	}
	
	fn = QFileDialog::getOpenFileName(this, "Ekxportuj baze danych", 
		QString(), tr("All files (*)"), NULL, QFileDialog::ReadOnly);
	if (fn.isEmpty())
		return;
	
	ret = filmbaza_export(fb, fn.toStdString());
	if ( ret )
		print("ekxportowanie nie udało się \n");
	else
		print("Wyeksportowano filmy do pliku " + fn.toStdString());
	
	refresh();
}

void MainWindow::film_new()
{
	std::string name;
	
	if ( !fb ) {
	        print("Baza danych nie została jeszcze utworzona");
		return;
	}
	
	bool ok;
        QString text = QInputDialog::getText(this, tr("Nowy film"),
						tr("Nazwa filmu:"), QLineEdit::Normal,
						QString(), &ok);
	if ( !ok || text.isEmpty() )
		return;
	
	name = text.toStdString();
	if ( filmbaza_add(fb, name) ) {
		print("Błąd dodawania nowego filmu");
	} else {
	//	print("Dodano nowy film o nazwie " + name);
	}
	
	refresh();
}

void MainWindow::film_del()
{
	int num, i;
	
	if ( !fb ) {
	        print("Baza danych nie została jeszcze utworzona");
		return;
	}	
	
	bool ok;
        num = QInputDialog::getInt(this, tr("Usuń film"),
						tr("Numer filmu:"),
						1, 0, ui->tabka->model()->rowCount(), 1, &ok);
	if ( !ok )
		return;
	
	/* get element number */
    struct film_s **head = &this->fb->filmy;
	struct film_s *film;
	
	/* iterujemy od zera, a wprowadzamy num od 1, więc i=num-1 */
	i = num-1;
    list_for_each(film, head) {
		if ( i-- == 0 ) break;
	}
	
	/* nie musimy sprawdzać if ( film ) bo QInputDIalog robi to za nas
	 * [ o ile  refresh() zadbał by ui->tabka->model()->rowCount() był odświerzony ] */
	filmbaza_delete(fb, film->id);
	
	refresh();
	print("Usunięto film");
}

void MainWindow::dirscan()
{
	std::string fn;
	
	fn = QFileDialog::getExistingDirectory(this, "Skanuj katalog w poszukiwaniu filmów",
		QString(), QFileDialog::ReadOnly).toStdString();
	if (fn.empty())
		return;
	
	print(fn);
	
	scan(fb, fn);

	refresh();
}

void MainWindow::on_actionNowa_filmbaza_triggered()
{	
	this->baza_new();
}

void MainWindow::on_actionUsun_filmbaze_triggered()
{
	this->baza_del();
}

void MainWindow::on_actionZako_cz_triggered()
{
	exit(0);
}

void MainWindow::on_actionEksportuj_triggered()
{
	this->export_base();
}

void MainWindow::on_actionImportuj_triggered()
{
	this->import_base();
}

void MainWindow::on_actionO_filmbazie_triggered()
{	
	QMessageBox::about(this, tr("O aplikacji"), tr(
		"<h3>  Filmbaza </h3>"
		"<p>Aplikacja zawierająca interfejs graficzny umożliwiający użytkownikowi "
		"zarządzanie oraz dowolną modyfikacje baz danych filmów.</p>"
		"<p>Za jej pomocą tworzenie, usuwanie bazy danych plików, jej importowanie "
		"i eksportowanie do pliku, dodawanie, usuwanie oraz edytowanie filmów "
		"znajdujących się w bazie danych, ich ocenianie oraz wypożyczanie znajomym "
		" dokonuje się niezwykle łatwo, sprawnie i przyjemnie.</p>"
		"<p><b>Filmbaza</b> to aplikacja stworzona przy pomocy środowiska graficznego"
		"QT 5.0.2 (64 Bit), w pełni napisana w języku programowanie c++."
		"Autorem <b>filmbazy</b> jest Kamil Cukrowski student uczelni PW grupa 11,"
		"który stworzył tę aplikacje na zaliczenie projektu z ZAP2.</p>"
		"<p>Licensed under Beerware license by Kamil Cukrowski <kamil@dyzio.pl> 2013</p>"
		"<p> hakunamatata, jak cudownie to brzmi </p>"
	) );
}

void MainWindow::on_actionDodaj_film_triggered()
{
	this->film_new();
}

void MainWindow::on_actionUsu_film_triggered()
{
	this->film_del();
}

void MainWindow::on_actionSkanuj_katalog_triggered()
{
	this->dirscan();
}

void MainWindow::on_buttonStworz_baze_clicked()
{
	this->baza_new();
}

void MainWindow::on_actionDodaj_u_ytkownika_triggered()
{
	bool ok;
        std::string user = QInputDialog::getText(this, tr("Dodaj użytkownika."),
						tr("Podaj nazwe użytkownika:"), QLineEdit::Normal,
						QString(), &ok).toStdString();
	if ( !ok || user.empty() )
	     return;
	
	
	std::string pass = QInputDialog::getText(this, tr("Dodaj użytkownika."),
						tr("Podaj hasło:"), QLineEdit::Normal,
						QString(), &ok).toStdString();
	if ( !ok || pass.empty() )
	     return;
	
	int mode = QInputDialog::getInt(this, tr("Dodaj użytkownika."),
                        tr("Czy jest adminem (0 jeśli nie, 1 jeśli tak:"),
						0, -1, 1, 1, &ok);
				       
	if ( !ok )
		return;
	
	login_useradd(user, pass, mode);
	
	refresh();
}

void MainWindow::on_actionUsu_u_ytkownika_triggered()
{
	bool ok;
        std::string user = QInputDialog::getText(this, tr("Usuń użytkownika."),
						tr("Podaj nazwe użytkownika:"), QLineEdit::Normal,
						QString(), &ok).toStdString();
	if ( !ok || user.empty() )
	     return;
	
	login_userdel(user);
	
	
    refresh();
}

void MainWindow::on_actionPrzeloguj_sie_triggered()
{
	bool ok;
        std::string user = QInputDialog::getText(this, tr("Przelogowanie sie."),
						tr("Podaj nazwe użytkownika:"), QLineEdit::Normal,
						QString(), &ok).toStdString();
	if ( !ok )
		return;
	
	
	std::string pass = QInputDialog::getText(this, tr("Przelogowanie sie."),
						tr("Podaj hasło:"), QLineEdit::Normal,
						QString(), &ok).toStdString();
	if ( !ok )
		return;
	
	int ret = uwierzytelnij(user, pass);	
	if ( ret < 0 ) {
		print("Nieprawidłowa nazwa użytkownika lub hasło");
	} else if ( ret == 0 ) {
		print("Zalogowano jako " + user);
	} else if ( ret == 1 ) {
		print("Zalogowano jako " + user + " z prawami administratora");
	}
	
	refresh();
}

void MainWindow::on_buttonUsu_baze_clicked()
{
    this->baza_del();
}

void MainWindow::on_buttonDodaj_film_clicked()
{
    this->film_new();
}

void MainWindow::on_buttonUsu_film_clicked()
{
    this->film_del();
}

void MainWindow::on_tabka_doubleClicked(const QModelIndex &index)
{
	const int col = index.column();
	const int row = index.row();
	int i;
	
	/* get element number row */
    struct film_s **head = &this->fb->filmy;
	struct film_s *film;
	
	i = row;
    list_for_each(film, head) {
		if ( i-- == 0 ) break;
	}
	
	if ( !film ) return;
	
	switch (col) {
	case 0:
	{
		bool ok;
        QString text = QInputDialog::getText(this, tr("Edycja nazww filmu."),
							tr("Nowa nazwa filmu:"), QLineEdit::Normal,
						     QString(), &ok);
		if ( !ok || text.isEmpty() )
		     return;
		film->name = text.toStdString();
	}
		break;
	case 1:
	{
		bool ok;
		int i = QInputDialog::getInt(this, tr("Edycja oceny filmu"),
							tr("Oceń film:"), 0, 0, 5, 1, &ok);
		if ( !ok )
			return;
		
		filmbaza_rate(fb, film->id, i);
	}
		break;
	case 2:
	{
		if ( film->share.shared ) {
			print("Zwrócono wypożyczony film przez " + film->share.name);
			filmbaza_unshare(fb, film->id);
		} else {	
			bool ok;
            QString text = QInputDialog::getText(this, tr("Edycja wypożyczenia.").toUtf8(),
								tr("Komu wypożyczasz film:"), QLineEdit::Normal,
							     QString(), &ok);
			if ( !ok || text.isEmpty() )
			     return;
			
			filmbaza_share(fb, film->id, text.toStdString());
		}
	}
		break;
	}
	
	refresh();
}

void MainWindow::on_actionSortuj_triggered()
{
	/* na pewno jest lepszy sposób by to zrobić, no ale z braku laku */
	
	QList<int> opt;
	QStringList kiedy_bylem;
	int i;
	
	QList<int> direction;
	QStringList malym_chlopcem;
	int j;
	
	QList<QString>::iterator itr;
	
	opt << FILMBAZA_SORT_NAME << FILMBAZA_SORT_RATE << FILMBAZA_SORT_SHARE_NAME << FILMBAZA_SORT_ID;
	kiedy_bylem << tr("nazwa") << tr("ocena") << tr("wypożyczone") << tr("id");
	
	direction << 1 << 0;
	malym_chlopcem << tr("malejąco")<< tr("rosnąco");
	
        bool ok;
        QString kaboom = QInputDialog::getItem(this, tr("Sortowanie"),tr("Wybierz pole, po którym chcesz posortować:"),
					kiedy_bylem, 0, false, &ok);
        if (!ok || kaboom.isEmpty())
		return;
	QString hakuna = QInputDialog::getItem(this, tr("Sortowanie"),tr("W którą strone mam sortować"),
						malym_chlopcem, 0, false, &ok);
        if (!ok || hakuna.isEmpty())
		return;
	
	
	for(itr = kiedy_bylem.begin(); itr != kiedy_bylem.end(); itr++) {
		if ( *itr == kaboom )
			break;
	}
	i = opt.value(std::distance(kiedy_bylem.begin(), itr));
	
	for(itr = malym_chlopcem.begin(); itr != malym_chlopcem.end(); itr++) {
		if ( *itr == hakuna )
			break;
	}
	j = direction.value(std::distance(malym_chlopcem.begin(), itr));
	
	filmbaza_sort(fb, i, j);
	
	refresh();
}
